/**
 * JFunny - A funny programming language
 * Copyright (C) 2013  fanguangping
 * Any problem email me: fguangping@gmail.com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 3
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **/
package org.jfunny.core;

import java.io.IOException;
import java.io.PushbackReader;
import java.io.StringReader;
import java.util.List;

import org.armedbear.lisp.Interpreter;
import org.jfunny.core.dfa.DFA;
import org.jfunny.core.ds.Statement;
import org.jfunny.core.ds.StatementMapping;
import org.jfunny.core.parser.ParserFunny;
import org.jfunny.core.parser.ParserTpl;
import org.jfunny.core.parser.ScannerFunny;
import org.jfunny.core.sys.ProjectEvaluator;
import org.jfunny.core.util.FileUtil;

/**
 * 泛语言翻译器主函数
 * 
 * @author fanguangping
 *
 */
public class JFunny {
	public static final String[] LANG_TEMPLATES = { "lang/std.tpl", "lang/list.tpl", "lang/math.tpl",
			"lang/predicate.tpl", "lang/object.tpl" };

	public static void main(String[] args) {
		if (args.length == 0) {
			System.out.println();
			System.out.println("JFunny usage:> java JFunny <filePath>");
			System.out.println();
		}
		else {
			Interpreter interpreter = Interpreter.getInstance();
			if (interpreter == null) {
				interpreter = Interpreter.createInstance();
			}

			String filePath = args[0];
			if (filePath.endsWith(".funny")) {
				System.out.println("interprete file: " + filePath);
				interpreteFunny(filePath);
			}
			else if (filePath.endsWith(".prj")) {
				System.out.println("interprete project: " + filePath);
				interpreteProject(filePath);
			}
			else {
				throw new RuntimeException("File not supported!");
			}
		}

		/*
		try {
			String funny = FileUtil.readTxt("example/sqrt.funny");
			String code = parse(funny);

			System.out.println(code);
			System.out.println("=====================");

			String[] lines = code.split("\n");
			for (String line : lines) {
				interpreter.eval(line);
			}
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		
		interpreteProject("D:/MyPrograms/java/jfunny/target/classes/example/project/project.prj");
		*/
	}

	public static void interpreteFunny(String filePath) {
		Interpreter interpreter = Interpreter.getInstance();
		if (interpreter == null) {
			interpreter = Interpreter.createInstance();
		}

		try {
			String funny = FileUtil.readTxt(filePath);
			String code = parse(funny);
			String[] lines = code.split("\n");
			for (String line : lines) {
				interpreter.eval(line);
			}
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void interpreteProject(String filePath) {
		try {
			String prj = FileUtil.readTxt(filePath);
			ProjectEvaluator.eval(filePath, prj);
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static String merge(String funny, String tpl) throws Exception {
		ParserFunny parserJ = new ParserFunny(new ScannerFunny(new PushbackReader(new StringReader(funny))));
		List<StatementMapping> statements = new ParserTpl(tpl).parseTemplate();

		StringBuffer buffer = new StringBuffer();
		while (parserJ.hasNext()) {
			Statement s = parserJ.next();

			String result = DFA.getInstance().match(s, statements);

			buffer.append(result);
			buffer.append("\n");
		}

		return buffer.toString();
	}

	public static String parse(String funny) throws Exception {
		StringBuffer buffer = new StringBuffer();

		for (String filePath : LANG_TEMPLATES) {
			String tpl = FileUtil.readTxt(filePath);
			buffer.append(tpl);
		}

		ParserFunny parser = new ParserFunny(new ScannerFunny(new PushbackReader(new StringReader(funny))));
		List<StatementMapping> statements = new ParserTpl(buffer.toString()).parseTemplate();

		buffer = new StringBuffer();
		while (parser.hasNext()) {
			Statement s = parser.next();

			String result = DFA.getInstance().match(s, statements);

			buffer.append(result);
			buffer.append("\n");
		}

		return buffer.toString();
	}
}
